/**
 **************************************************************************************************************************
 * 
 **************************************************************************************************************************
 * @file RBSmartPointer.h
 **************************************************************************************************************************/


#ifndef __RBSMARTPOINTER_H__
#define __RBSMARTPOINTER_H__


/**************************************************************************************************************************
 * Includes
 **************************************************************************************************************************/

/**************************************************************************************************************************
 * Forward declarations
 **************************************************************************************************************************/

/**************************************************************************************************************************
 * Classes
 **************************************************************************************************************************/

template <class T> class RBSmartPointer
{
public:
                    RBSmartPointer  (T* pObject = (T*) 0);
                    RBSmartPointer  (const RBSmartPointer& ptr);
    virtual        ~RBSmartPointer  ();

                    operator T*     () const;
    T&              operator *      () const;
    T*              operator ->     () const;

    RBSmartPointer& operator=(const RBSmartPointer& ptr);
    RBSmartPointer& operator=(T* pObject);

    bool operator==(T* pObject) const;
    bool operator!=(T* pObject) const;
    bool operator==(const RBSmartPointer& ptr) const;
    bool operator!=(const RBSmartPointer& ptr) const;
    bool operator <(const RBSmartPointer& ptr) const;

protected:
    T* m_pObject;
};

#define RBDeclareSmartPointer(classname)                \
    class classname;                                    \
    typedef RBSmartPointer< classname > classname##Ptr

#define RBSmartPointerCast(type, ptr) ((type*) (void*) (ptr))

/**
 **************************************************************************************************************************
 * 
 **************************************************************************************************************************/
template <class T>
 RBSmartPointer<T>::RBSmartPointer(T* pObject)
{
    m_pObject = pObject;
    if (m_pObject)
        m_pObject->IncRefCount();
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 RBSmartPointer<T>::RBSmartPointer(const RBSmartPointer& ptr)
{
    m_pObject = ptr.m_pObject;
    if (m_pObject)
        m_pObject->IncRefCount();
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 RBSmartPointer<T>::~RBSmartPointer()
{
    if (m_pObject)
        m_pObject->DecRefCount();
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 RBSmartPointer<T>::operator T*() const
{
    return m_pObject;
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 T& RBSmartPointer<T>::operator*() const
{
    return *m_pObject;
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 T* RBSmartPointer<T>::operator->() const
{
    return m_pObject;
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 RBSmartPointer<T>& RBSmartPointer<T>::operator=(const RBSmartPointer& ptr)
{
    if (m_pObject != ptr.m_pObject)
    {
        if (m_pObject)
            m_pObject->DecRefCount();
        m_pObject = ptr.m_pObject;
        if (m_pObject)
            m_pObject->IncRefCount();
    }
    return *this;
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 RBSmartPointer<T>& RBSmartPointer<T>::operator=(T* pObject)
{
    if (m_pObject != pObject)
    {
        if (m_pObject)
            m_pObject->DecRefCount();
        m_pObject = pObject;
        if (m_pObject)
            m_pObject->IncRefCount();
    }
    return *this;
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 bool RBSmartPointer<T>::operator==(T* pObject) const
{
    return (m_pObject == pObject);
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 bool RBSmartPointer<T>::operator!=(T* pObject) const
{
    return (m_pObject != pObject);
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 bool RBSmartPointer<T>::operator==(const RBSmartPointer& ptr) const
{
    return (m_pObject == ptr.m_pObject);
}

/**
**************************************************************************************************************************
* 
**************************************************************************************************************************/
template <class T>
 bool RBSmartPointer<T>::operator!=(const RBSmartPointer& ptr) const
{
    return (m_pObject != ptr.m_pObject);
}

template <class T>
bool RBSmartPointer<T>::operator<(const RBSmartPointer& ptr) const
{
    return m_pObject < ptr.m_pObject;
}

/**************************************************************************************************************************/

#endif // __RBSMARTPOINTER_H__
